package com.cloudansys.schedule;

import com.alibaba.fastjson.JSON;
import com.cloudansys.core.constant.Const;
import com.cloudansys.core.util.JedisUtil;
import com.cloudansys.core.util.MysqlUtil;
import com.cloudansys.hawkeye.modules.settings.model.BaseTargetData;
import com.cloudansys.hawkeye.modules.settings.model.BaseThreshold;
import com.cloudansys.hawkeye.modules.settings.model.vo.DataWarn;
import com.cloudansys.hawkeye.modules.settings.model.vo.PrimaryWarn;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Data
@Slf4j
class SaveWarnJob implements Runnable {

    /**
     * 定时把缓存在 redis 中的告警信息存储到 MySQL 中
     */
    @Override
    public void run() {
//        log.info("----<SaveWarnsToMysql>----");

        // 获取缓存在 redis 中的告警信息
        List<DataWarn> warnsInRedis = getWarnsInRedis();

        // 批量插入
        if (warnsInRedis.size() != 0) {
            MysqlUtil.save(warnsInRedis);
            log.info("##### save warns to mysql success #####");
        }
    }

    /**
     * 获取缓存在 redis 中的告警信息
     */
    private List<DataWarn> getWarnsInRedis() {
        String jsonString;
        PrimaryWarn primaryWarn = null;
        List<DataWarn> dataWarns = new ArrayList<>();
        try {
            // 判断 redis 是否缓存的有告警对象
            String redisWarnsKey = JedisUtil.getWarnKey();
            while ((jsonString = JedisUtil.lPop(redisWarnsKey)) != null) {
                try {
                    primaryWarn = JSON.parseObject(jsonString, PrimaryWarn.class);
                } catch (Exception e) {
                    log.error("告警对象解析失败！【SaveToMysqlJob】");
                    e.printStackTrace();
                }

                // 封装数据库存储告警对象
                if (primaryWarn != null) {
                    DataWarn dataWarn = wrapObj(primaryWarn);
                    dataWarns.add(dataWarn);
                }
            }
        } catch (Exception e) {
            log.error("errMsg: " + e.getMessage());
            e.printStackTrace();
        }
        return dataWarns;
    }

    /**
     * 组织告警存储对象
     */
    private DataWarn wrapObj(PrimaryWarn primaryWarn) {
        String dataJson = getDataJson(primaryWarn);
        String thresholdJson = getThresholdJson(primaryWarn);
        return DataWarn.builder()
                .targetId(primaryWarn.getTargetId())
                .targetTypeId(primaryWarn.getTargetTypeId())
                .dataJson(dataJson)
                .thresholdJson(thresholdJson)
                .timeO(getDate(primaryWarn.getDataTime()))
                .timeW(new Date())
                .quotaId(primaryWarn.getQuotaId())
                .level(primaryWarn.getLevel())
                .message(primaryWarn.getMessage())
                .build();
    }

    /**
     * @param s 时间字符串，格式：标准格式
     * @return 返回格式化后的时间
     */
    private Date getDate(String s) {
        SimpleDateFormat format = new SimpleDateFormat(Const.FMT_STD_SEC);
        try {
            return format.parse(s);
        } catch (ParseException e) {
            log.error("时间格式化错误！【SaveJob】");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param primaryWarn 告警对象
     * @return 返回 BaseTargetData 的 Json 对象
     */
    private String getDataJson(PrimaryWarn primaryWarn) {
        BaseTargetData baseTargetData = BaseTargetData.builder()
                .id(primaryWarn.getTargetId())
                .time(primaryWarn.getDataTime())
                .data(primaryWarn.getRawData())
                .build();
        return JSON.toJSONString(baseTargetData);
    }

    /**
     * @param primaryWarn 告警对象
     * @return 返回 BaseThreshold 的 Json 对象
     */
    private String getThresholdJson(PrimaryWarn primaryWarn) {
        BaseThreshold baseThreshold = BaseThreshold.builder()
                .id(primaryWarn.getThresholdId())
                .targetId(primaryWarn.getTargetId())
                .quotaId(primaryWarn.getQuotaId())
                .quotaCode(primaryWarn.getQuotaCode())
                .quotaName(primaryWarn.getQuotaName())
                .quotaUnit(primaryWarn.getQuotaUnit())
                .dataValue(primaryWarn.getDataValue())
                .name(primaryWarn.getThresholdName())
                .level(primaryWarn.getLevel())
                .lower(primaryWarn.getLower())
                .upper(primaryWarn.getUpper())
                .absolute(primaryWarn.getAbsolute())
                .build();
        return JSON.toJSONString(baseThreshold);
    }

}
